package com.zjut.szq.demo.dao.impl;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;

import com.zjut.szq.demo.dao.BaseDAO;


/** 统一数据访问接口实现 */
@Repository("baseDao")
public class BaseDAOImpl<T> implements BaseDAO<T> {

	private SessionFactory sessionFactory;
	
	@Resource(name = "sessionFactory")
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	protected Session getSession()
	{
		return this.sessionFactory.getCurrentSession();
	}
	
	@Override
	public void save(T obj) {
		getSession().save(obj);
	}

	@Override
	public void saveOrUpdate(T obj) {
		getSession().saveOrUpdate(obj);
	}

	@Override
	public void deleteById(Class<T> clazz, Serializable id) {
		getSession().delete(getSession().load(clazz, id));
	}

	@Override
	public void delete(T obj) {
		getSession().delete(obj);
	}

	@Override
	public Object loadById(Class<T> clazz, Serializable id) {
		return getSession().get(clazz, id);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<T> findByHql(String hql, int start, int limit, Object... params) {
		Query query = getSession().createQuery(hql);
		for (int i = 0; params != null && i < params.length; i++) {
			query.setParameter(i, params[i]);
		}
		if (start >= 0 && limit > 0) {
			query.setFirstResult(start);
			query.setMaxResults(limit);
		}
		return query.list();
	}

	@Override
	public List<T> findByHql(String hql) {
		return findByHql(hql, 0, 0);
	}
	
	@Override
	public List<T> findByHql(String hql, Object... params) {
		return findByHql(hql, 0, 0, params);
	}
	
	@Override
	public List<T> listAll(Class<T> clazz) {
		return findByHql("from " + clazz.getName());
	}
	
	@Override
	public List<T> listAll(Class<T> clazz, int start, int limit) {
		String hql = "from " + clazz.getName();
		return findByHql(hql, start, limit);
	}

	@Override
	public List<T> findByProperty(Class<T> clazz, String propertyName, Object value) {
		String hql = "from " + clazz.getName() + " as model where model." + propertyName
				+ "= ?";
		return findByHql(hql, value);
	}

	@Override
	public List<T> findByProperty(Class<T> clazz, String[] propertyName,
			Object[] value) {
		String hsql = "from " + clazz.getName() + " as model where 1=1";
		for (int i = 0; i < propertyName.length; i++) {
			hsql += " and model." + propertyName[i] + "= ?";
		}
		return findByHql(hsql, value);
	}
	
	@Override
	public List<T> findByProperty(Class<T> clazz, String propertyName, String value,
			int start, int limit) {
		String hql = "from " + clazz.getName() + " as model where model." + propertyName
				+ "= ?";
		return this.findByHql(hql, start, limit, value);
	}

	@Override
	public List<T> findByProperty(Class<T> clazz, String[] propertyName,
			Object[] value, int start, int limit) {
		String hql = "from " + clazz.getName() + " as model where 1=1";
		for (int i = 0; i < propertyName.length; i++) {
			hql += " and model." + propertyName[i] + "= ? ";
		}
		return this.findByHql(hql, start, limit, value);
	}
	
	@Override
	public List<T> findInProperty(Class<T> clazz, String propertyName, String value) {
		String hql = "from " + clazz.getName() + " as model where model." + propertyName
				+ " in ( ? )";
		return findByHql(hql, value);
	}
	
	@Override
	public List<T> findInProperty(Class<T> clazz, String propertyName, String value,
			int start, int limit) {
		String hql = "from " + clazz.getName() + " as model where model." + propertyName
				+ " in ( ? )";
		return this.findByHql(hql, start, limit, value);
	}

	@Override
	public List<T> findLikeProperty(Class<T> clazz, String propertyName, String value) {
		String hql = "from " + clazz.getName() + " as model where model." + propertyName
				+ " like ?";
		return findByHql(hql, value);
	}

	@Override
	public List<T> findLikeProperty(Class<T> clazz, String propertyName,
			String value, int start, int limit) {
		String hql = "from " + clazz.getName() + " as model where model." + propertyName
				+ " like ?";
		return this.findByHql(hql, start, limit, value);
	}

	@Override
	public int countAll(Class<T> clazz) {
		final String hql = "select count(*) from " + clazz.getName();
		return countQuery(hql);
	}
	
	@Override
	public int countQuery(String hql) {
		Query query = getSession().createQuery(hql);
		query.setMaxResults(1);
		Long count =  (Long)query.uniqueResult();
		return count.intValue();
	}

	@Override
	public int countQuery(String hql, Object[] value) {
		final String counthql = hql;
		Query query = getSession().createQuery(counthql);
		for (int i = 0; value != null && i < value.length; i++) {
			query.setParameter(i, value[i]);
		}
		query.setMaxResults(1);
		Long count =  (Long)query.uniqueResult();
		return count.intValue();
	}

	@Override
	public void saveOrUpdateAll(Object[] objects) {
		Session session = getSession();
		for (int i = 0; objects != null && i < objects.length; i++) 
		{
			session.saveOrUpdate(objects[i]);
			if (i%20 == 0)
			{
				session.flush();
				session.clear();
			}
		}
	}

	@Override
	public boolean executeSql(String sql) {
		getSession().createSQLQuery(sql).executeUpdate();
		getSession().flush();
		getSession().clear();
		return true;
	}

}